package org.apache.ibatis.common.reflection.invoker;

import org.apache.ibatis.common.reflection.Reflector;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Name MethodInvoker
 * @Description: {调用目标方法} 执行器 [实现] 类
 * @Version v1.0.0
 * @Author: lichao
 * @Date: 2024-04-25 15:27:21
 **/
public class MethodInvoker implements Invoker {
    // 目标方法
    private final Method method;
    // 目标方法入参或返回值的类型
    private final Class<?> type;

    public MethodInvoker(Method method) {
        this.method = method;
        if (this.method.getParameterTypes().length == 1) {
            this.type = method.getParameterTypes()[0];
        } else {
            this.type = method.getReturnType();
        }
    }

    @Override
    public Class<?> getType() {
        return type;
    }

    @Override
    public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
        try {
            // 1. 直接通过反射获取调用目标方法
            return method.invoke(target, args);
        } catch (IllegalAccessException e) {
            // 如果发生异常，则修改目标方法的访问权限后再次尝试调用目标方法
            if (Reflector.canControlMemberAccessible()) {
                method.setAccessible(true);
                return method.invoke(target, args);
            } else {
                throw e;
            }
        }
    }
}

